package com.hj.base;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

import com.hj.base.impl.FragmentInterface;
import com.hj.base.impl.IBaseImpl;
import com.hj.base.impl.IBaseView;
import com.hj.base.impl.IntentCallBackInterface;
import com.hj.controller.ControlObserver;
import com.hj.controller.Controller;
import com.hj.controller.ControllerParamBean;
import com.hj.controller.ObserverCallback;
import com.hj.easypremissions.EasyPermissions;
import com.hj.easypremissions.helper.PermissionHelper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by hp on 2018/4/26.
 */

public class BaseListFragment extends Fragment implements IBaseView, IBaseImpl, FragmentInterface, EasyPermissions.PermissionCallbacks {
    protected final String TAG = this.getClass().getSimpleName();
    private int CONTENT_ID = 4353;
    protected Activity activity;
    protected Context context;
    private View contentView;
    protected boolean isViewCreated = false;//是否已经CreateView
    private List<BaseFragment> fgList = new ArrayList<>();
    private Dialog dialog;
    private ProgressDialog progressDialog;
    private ControlObserver observer = new ControlObserver() {
        @Override
        public void execute(Activity activity, String command, ControllerParamBean params, ObserverCallback callback) {
            BaseListFragment.this.noticeReceiver(activity, command, params, callback);
        }
    };
    private int requestCode;
    private IntentCallBackInterface intentCallBack;
    public final int REQUEST_CODE = 10000;
    public final int STORAGE_CODE = 131;
    public final String[] STORAGE_PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE};

    public final int CAMERA_CODE = 132;
    public final String[] CAMERA_PERMISSIONS = new String[]{Manifest.permission.CAMERA};

    public final int BLUETOOTH_CODE = 133;
    public final String[] BLUE_PERMISSIONS = new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};

    private EasyPermissions.Callback callbacks;

    /**
     * 接收指令
     *
     * @param activity
     * @param command
     * @param params
     * @param callback
     */
    public void noticeReceiver(Activity activity, String command, ControllerParamBean params, ObserverCallback callback) {

    }


    @Override
    public void setWindowParams() {

    }

    @Override
    public int setContentViewId() {
        return 0;
    }

    protected int setFrameLayoutId() {
        return CONTENT_ID;
    }

    @Override
    public void initView() {
//        String className = this.getArguments().getString(Constant.FRAGMENT_CLASSNAME_KEY);
//        if (className == null || "".equals(className)) {
//            showToast("类名信息为空！");
//            this.finishFragment();
//        }
//
//        Log.d(TAG, "className:" + className);
//
//        try {
//            Class cs = Class.forName(className);
//            if (this.isBaseFragment(cs)) {
//                this.baseFragment = (BaseFragment) cs.newInstance();
//                this.baseFragment.setArguments(getArguments());
//                this.startFragment(this.baseFragment, false);
//            } else {
//                Log.e("ActionFragment", "Exception:Fragment类型不是BaseFragment！");
//                showToast("类名信息解析失败，类型错误！");
//                this.finishFragment();
//            }
//        } catch (Exception var5) {
//            Log.e("ActionFragment", "Exception:类名信息解析失败，未找到目标！className:" + className);
//            showToast("类名信息解析失败，未找到目标！className:" + className);
//            this.finishFragment();
//        }
    }

    @Override
    public void initData() {

    }

    @Override
    public void initListener() {

    }

    /**
     * Fragment与Activity已经完成绑定
     *
     * @param activity
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.d(TAG, "### onAttach Activity ###");
        this.activity = activity;
        Controller.registerObserver(this.observer);
    }

    /**
     * Fragment与Context已经完成绑定
     *
     * @param context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.d(TAG, "### onAttach Context ###");
        this.context = context;
    }

    /**
     * 初始化Fragment
     *
     * @param savedInstanceState
     */
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "### onCreate ###");
    }

    /**
     * 初始化Fragment的布局
     *
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.d(TAG, "### onCreateView ###");
        //设置布局视图
        CONTENT_ID = setFrameLayoutId();
        if (setContentViewId() == 0) {
            FrameLayout frameLayout = new FrameLayout(this.activity);
            frameLayout.setId(CONTENT_ID);
            this.contentView = frameLayout;
        } else {
            contentView = inflater.inflate(setContentViewId(), container, false);
        }

        return this.contentView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.d(TAG, "### onViewCreated ###");
        isViewCreated = true;
        //初始化控件
        initView();
    }

    /**
     * 与Fragment绑定的Activity的onCreate方法已经执行完成并返回，
     * 在该方法内可以进行与Activity交互的UI操作，
     * 所以在该方法之前Activity的onCreate方法并未执行完成，
     * 如果提前进行交互操作，会引发空指针异常。
     *
     * @param savedInstanceState
     */
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "### onActivityCreated ###");
        //初始化数据
        initData();
        //初始化监听事件
        initListener();
    }

    /**
     * Fragment由不可见变为可见状态
     */
    @Override
    public void onStart() {
        super.onStart();
        Log.d(TAG, "### onStart ###");
    }

    /**
     * Fragment处于活动状态，用户可与之交互。
     */
    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "### onResume ###");
    }

    /**
     * Fragment处于暂停状态，但依然可见，用户不能与之交互。
     */
    @Override
    public void onPause() {
        super.onPause();
        Log.d(TAG, "### onPause ###");
    }

    /**
     * Fragment完全不可见
     */
    @Override
    public void onStop() {
        super.onStop();
        Log.d(TAG, "### onStop ###");
    }

    /**
     * 销毁与Fragment有关的视图，但未与Activity解除绑定，依然可以通过onCreateView方法重新创建视图。
     */
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.d(TAG, "### onDestroyView ###");
        isViewCreated = false;
    }

    /**
     * 销毁Fragment。
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "### onDestroy ###");
    }

    /**
     * 解除与Activity的绑定。在onDestroy方法之后调用。
     */
    @Override
    public void onDetach() {
        super.onDetach();
        Log.d(TAG, "### onDetach ###");
        hideLoading();
        dimissDialog();
        this.fgList.clear();
        this.fgList = null;
        this.context = null;
        this.activity = null;
        this.contentView = null;
        this.intentCallBack = null;
        Controller.unregisterObserver(this.observer);
    }

    @SuppressLint("WrongConstant")
    @Override
    public void startFragment(BaseFragment fragment, boolean animation) {
        if (this.fgList.contains(fragment)) {
            Log.i(TAG, "the fragmentlist has contains this fragment.");
            this.fgList.remove(fragment);
        }
        this.fgList.add(fragment);
        FragmentTransaction fragmentTransaction = this.getChildFragmentManager().beginTransaction();
        if (animation) {
            fragmentTransaction.setTransition(4097);
        }

        fragmentTransaction.replace(CONTENT_ID, fragment);
        fragmentTransaction.commitAllowingStateLoss();
    }

    @SuppressLint("WrongConstant")
    @Override
    public void finishFragment() {
        if (this.fgList.size() > 1) {
            this.fgList.remove(this.fgList.size() - 1);
            FragmentTransaction fragmentTransaction = this.getChildFragmentManager().beginTransaction();
            fragmentTransaction.setTransition(8194);
            fragmentTransaction.replace(CONTENT_ID, this.fgList.get(this.fgList.size() - 1));
            fragmentTransaction.commitAllowingStateLoss();
        } else {
            this.activity.finish();
        }
    }

    @SuppressLint("WrongConstant")
    @Override
    public void backToFragment(BaseFragment var1) {
        int index = fgList.indexOf(var1);
        Log.i(TAG, "index=" + index);
        if (index >= 0) {
            while (this.fgList.size() - 1 > index) {
                this.fgList.remove(this.fgList.size() - 1);
            }
            FragmentTransaction fragmentTransaction = this.getChildFragmentManager().beginTransaction();
            fragmentTransaction.setTransition(8194);
            fragmentTransaction.replace(CONTENT_ID, this.fgList.get(this.fgList.size() - 1));
            fragmentTransaction.commitAllowingStateLoss();
        }
    }

    @Override
    public void finishAllFragment() {
        this.activity.finish();
    }

    @Override
    public void showToast(String msg) {
        Toast.makeText(this.context, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showDialog(Dialog dialog) {
        if (this.dialog != null)
            this.dialog.dismiss();
        this.dialog = dialog;
        this.dialog.show();
    }

    @Override
    public void dimissDialog() {
        if (this.dialog != null)
            this.dialog.dismiss();
        this.dialog = null;
    }

    @Override
    public void showLoading() {
        if (progressDialog == null)
            progressDialog = new ProgressDialog(this.context);
        progressDialog.show();
    }

    @Override
    public void hideLoading() {
        if (progressDialog != null)
            progressDialog.dismiss();
        this.progressDialog = null;
    }

    @Override
    public Context mContext() {
        return this.context;
    }

    @Override
    public Activity mActivity() {
        return this.activity;
    }

    protected final <T extends View> T findViewById(int id) {
        return contentView.findViewById(id);
    }

    public List<BaseFragment> getFragmentList() {
        return fgList;
    }

    public View getContentView() {
        return contentView;
    }

    public boolean isBaseFragment(Class<?> c) {
        return BaseFragment.class.isAssignableFrom(c);
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {
        this.requestCode = requestCode;
        this.intentCallBack = null;
        super.startActivityForResult(intent, requestCode);
    }

    public void startActivityForResult(Intent intent, int requestCode, IntentCallBackInterface callBack) {
        startActivityForResult(intent, requestCode);
        this.intentCallBack = callBack;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == this.requestCode) {
            if (intentCallBack != null) {
                if (resultCode == Activity.RESULT_OK) {
                    intentCallBack.onResultOK(data);
                } else if (resultCode == Activity.RESULT_CANCELED) {
                    intentCallBack.onResultCanceled(data);
                } else if (resultCode == Activity.RESULT_FIRST_USER) {
                    intentCallBack.onResultFirstUser(data);
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    public int getRequestCode() {
        return requestCode;
    }

    public IntentCallBackInterface getIntentCallBack() {
        return intentCallBack;
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    public void hasStoragePermissions(EasyPermissions.Callback callbacks) {
        requestPermission(callbacks, STORAGE_CODE, STORAGE_PERMISSIONS);
    }

    public void hasCameraPermissions(EasyPermissions.Callback callbacks) {
        requestPermission(callbacks, CAMERA_CODE, CAMERA_PERMISSIONS);
    }

    public void hasBluePermissions(EasyPermissions.Callback callbacks) {
        requestPermission(callbacks, BLUETOOTH_CODE, BLUE_PERMISSIONS);
    }

    public void requestPermission(EasyPermissions.Callback callbacks, int requestCode, @NonNull String... permissions) {
        this.callbacks = null;
        if (EasyPermissions.hasPermissions(mContext(), permissions)) {
            if (callbacks != null) {
                callbacks.onGranted(requestCode, Arrays.asList(permissions));
            }
        } else {
            this.callbacks = callbacks;
            PermissionHelper.newInstance(this).directRequestPermissions(requestCode, permissions);
        }
    }

    public void requestPermission(EasyPermissions.Callback callbacks, @NonNull String... permissions) {
        requestPermission(callbacks, REQUEST_CODE, permissions);
    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        if (callbacks != null) {
            callbacks.onGranted(requestCode, perms);
        }
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        if (callbacks != null) {
            callbacks.onDenied(requestCode, perms);
        }
    }
}
